import re
import hashlib
import markdown
import bleach
from datetime import datetime
from flask import current_app, abort
from functools import wraps
from flask_login import current_user

def generate_slug(text):
    """生成URL友好的slug"""
    if not text:
        return 'untitled'
    
    # 转换为小写
    text = text.lower()
    
    # 移除HTML标签
    text = re.sub(r'<[^>]+>', '', text)
    
    # 替换中文字符为拼音（这里简化处理，实际项目中可以使用pypinyin）
    # 将中文替换为拼音或直接移除
    text = re.sub(r'[\u4e00-\u9fff]+', '', text)
    
    # 替换非字母数字字符为连字符
    text = re.sub(r'[^\w\s-]', '', text)
    
    # 替换空格和多个连字符为单个连字符
    text = re.sub(r'[\s_-]+', '-', text)
    
    # 移除首尾的连字符
    text = text.strip('-')
    
    # 如果结果为空，返回默认值
    if not text:
        return 'untitled'
    
    return text

def generate_excerpt(content, length=200):
    """从内容中生成摘要"""
    if not content:
        return ''
    
    # 移除HTML标签
    text = re.sub(r'<[^>]+>', '', content)
    
    # 移除多余的空白字符
    text = re.sub(r'\s+', ' ', text).strip()
    
    # 截取指定长度
    if len(text) <= length:
        return text
    
    # 在单词边界截取
    text = text[:length]
    last_space = text.rfind(' ')
    if last_space > length * 0.8:  # 如果最后一个空格位置合理
        text = text[:last_space]
    
    return text + '...'

def markdown_to_html(markdown_text):
    """将Markdown转换为HTML"""
    if not markdown_text:
        return ''
    
    # 配置Markdown扩展
    extensions = [
        'markdown.extensions.extra',
        'markdown.extensions.codehilite',
        'markdown.extensions.toc',
        'markdown.extensions.tables',
        'markdown.extensions.fenced_code'
    ]
    
    # 转换Markdown为HTML
    html = markdown.markdown(markdown_text, extensions=extensions)
    
    # 清理HTML，只允许安全的标签
    allowed_tags = [
        'p', 'br', 'strong', 'em', 'u', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
        'ul', 'ol', 'li', 'blockquote', 'code', 'pre', 'a', 'img',
        'table', 'thead', 'tbody', 'tr', 'th', 'td'
    ]
    
    allowed_attributes = {
        'a': ['href', 'title'],
        'img': ['src', 'alt', 'title', 'width', 'height'],
        'table': ['class'],
        'th': ['class'],
        'td': ['class']
    }
    
    html = bleach.clean(html, tags=allowed_tags, attributes=allowed_attributes)
    
    return html

def format_datetime(dt, format='%Y-%m-%d %H:%M'):
    """格式化日期时间"""
    if not dt:
        return ''
    
    if isinstance(dt, str):
        try:
            dt = datetime.fromisoformat(dt.replace('Z', '+00:00'))
        except:
            return dt
    
    return dt.strftime(format)

def format_relative_time(dt):
    """格式化相对时间（如：2小时前）"""
    if not dt:
        return ''
    
    if isinstance(dt, str):
        try:
            dt = datetime.fromisoformat(dt.replace('Z', '+00:00'))
        except:
            return dt
    
    now = datetime.utcnow()
    diff = now - dt
    
    if diff.days > 0:
        return f"{diff.days}天前"
    elif diff.seconds > 3600:
        hours = diff.seconds // 3600
        return f"{hours}小时前"
    elif diff.seconds > 60:
        minutes = diff.seconds // 60
        return f"{minutes}分钟前"
    else:
        return "刚刚"

def generate_gravatar_url(email, size=80):
    """生成Gravatar头像URL"""
    if not email:
        return ''
    
    # 生成MD5哈希
    hash_value = hashlib.md5(email.lower().encode('utf-8')).hexdigest()
    
    # 构建Gravatar URL
    return f"https://www.gravatar.com/avatar/{hash_value}?s={size}&d=identicon"

def truncate_text(text, length=100, suffix='...'):
    """截断文本"""
    if not text or len(text) <= length:
        return text
    
    return text[:length].rsplit(' ', 1)[0] + suffix

def extract_keywords(text, count=5):
    """从文本中提取关键词（简单实现）"""
    if not text:
        return []
    
    # 移除HTML标签
    text = re.sub(r'<[^>]+>', '', text)
    
    # 转换为小写并分词
    words = re.findall(r'\b\w+\b', text.lower())
    
    # 过滤停用词（简单列表）
    stop_words = {
        '的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都', '一', '一个', '上', '也', '很', '到', '说', '要', '去', '你', '会', '着', '没有', '看', '好', '自己', '这',
        'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for', 'of', 'with', 'by', 'is', 'are', 'was', 'were', 'be', 'been', 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could', 'should'
    }
    
    # 过滤停用词并统计词频
    word_count = {}
    for word in words:
        if len(word) > 2 and word not in stop_words:
            word_count[word] = word_count.get(word, 0) + 1
    
    # 按词频排序并返回前N个
    keywords = sorted(word_count.items(), key=lambda x: x[1], reverse=True)
    return [word for word, count in keywords[:count]]

def validate_email(email):
    """验证邮箱格式"""
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return re.match(pattern, email) is not None

def validate_url(url):
    """验证URL格式"""
    pattern = r'^https?://[^\s/$.?#].[^\s]*$'
    return re.match(pattern, url) is not None

def sanitize_filename(filename):
    """清理文件名，移除不安全字符"""
    # 移除路径分隔符和其他不安全字符
    filename = re.sub(r'[<>:"/\\|?*]', '', filename)
    # 移除控制字符
    filename = re.sub(r'[\x00-\x1f\x7f]', '', filename)
    # 限制长度
    if len(filename) > 255:
        name, ext = os.path.splitext(filename)
        filename = name[:255-len(ext)] + ext
    return filename

def get_file_size_human(size_bytes):
    """将字节数转换为人类可读的格式"""
    if size_bytes == 0:
        return "0 B"
    
    size_names = ["B", "KB", "MB", "GB", "TB"]
    i = 0
    while size_bytes >= 1024 and i < len(size_names) - 1:
        size_bytes /= 1024.0
        i += 1
    
    return f"{size_bytes:.1f} {size_names[i]}"

def admin_required(f):
    """需要管理员权限的装饰器"""
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if not current_user.is_authenticated:
            abort(401)  # 未登录
        if current_user.role != 'admin':
            abort(403)  # 权限不足
        return f(*args, **kwargs)
    return decorated_function

def author_required(f):
    """需要作者权限的装饰器（包括admin和author）"""
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if not current_user.is_authenticated:
            abort(401)  # 未登录
        if current_user.role not in ['admin', 'author']:
            abort(403)  # 权限不足
        return f(*args, **kwargs)
    return decorated_function
